package com.china08.yxyapi.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Component;

/**
 * 日期工具类 默认使用 "yyyy-MM-dd HH:mm:ss" 格式化日期
 * 
 */
@Component
public final class DateToolUtils {
    /**
     * 英文简写（默认）如：2010-12-01
     */
    public static String FORMAT_SHORT_YMD = "yyyy-MM-dd";
    /**
     * 英文简写（默认）如：2010-12
     */
    public static String FORMAT_SHORT_YM = "yyyy-MM";
    /**
     * 英文简写（默认）如：2010-12
     */
    public static String FORMAT_SHORT_Y = "yyyy";
    /**
     * 英文简写（默认）如：23:15:06
     */
    public static String FORMAT_SHORT_HMS = "HH:mm:ss";
    /**
     * 英文全称 如：2010-12-01 23:15:06
     */
    public static String FORMAT_LONG = "yyyy-MM-dd HH:mm:ss";
    /**
     * 英文全称 如：20101201231506123
     */
    public static String FORMAT_LONG_SSS = "yyyyMMddHHmmssSSS";
    /**
     * 精确到毫秒的完整时间 如：yyyy-MM-dd HH:mm:ss.S
     */
    public static String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss.S";
    /**
     * 中文简写 如：2010年12月01日
     */
    public static String FORMAT_SHORT_CN_YMD = "yyyy年MM月dd日";
    /**
     * 中文简写 如：23时15分06秒
     */
    public static String FORMAT_SHORT_CN_HMS = "HH时mm分ss秒";
    /**
     * 中文全称 如：2010年12月01日 23时15分06秒
     */
    public static String FORMAT_LONG_CN = "yyyy年MM月dd日  HH时mm分ss秒";
    /**
     * 精确到毫秒的完整中文时间
     */
    public static String FORMAT_FULL_CN = "yyyy年MM月dd日  HH时mm分ss秒SSS毫秒";

    /**
     * 获得默认的 date pattern
     */
    public static String getDatePattern() {
        return FORMAT_LONG;
    }

    /**
     * 根据预设格式返回当前日期
     * 
     * @return
     */
    public static String getNow() {
        return format(new Date());
    }

    /**
     * 根据用户格式返回当前日期
     * 
     * @param format
     * @return
     */
    public static String getNow(String format) {
        return format(new Date(), format);
    }

    /**
     * 使用预设格式格式化日期
     */
    public static String format(Date date) {
        return format(date, getDatePattern());
    }

    /**
     * 使用用户格式格式化日期
     * 
     * @param date
     *            日期
     * @param pattern
     *            日期格式
     * @return
     */
    public static String format(Date date, String pattern) {
        String returnValue = "";
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            returnValue = df.format(date);
        }
        return returnValue;
    }

    /**
     * 使用预设格式提取字符串日期
     * 
     * @param strDate
     *            日期字符串
     * @return
     */
    public static Date parse(String strDate) {
        return parse(strDate, getDatePattern());
    }

    /**
     * 使用用户格式提取字符串日期
     * 
     * @param strDate
     *            日期字符串
     * @param pattern
     *            日期格式
     * @return
     */
    public static Date parse(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) return null;
        SimpleDateFormat df = new SimpleDateFormat(pattern);
        try {
            return df.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 在日期上增加数个整月
     * 
     * @param date
     *            日期
     * @param n
     *            要增加的月数
     * @return
     */
    public static Date addMonth(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, n);
        return cal.getTime();
    }

    /**
     * 在日期上增加天数
     * 
     * @param date
     *            日期
     * @param n
     *            要增加的天数
     * @return
     */
    public static Date addDay(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, n);
        return cal.getTime();
    }

    /**
     * 获取给定时间的时间戳
     */
    public static String getTimeString(Date date) {
        SimpleDateFormat df = new SimpleDateFormat(DateToolUtils.FORMAT_LONG_SSS);
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        return df.format(calendar.getTime());
    }

    /**
     * 获取当前时间的时间戳
     */
    public static String getNowTimeString() {
        SimpleDateFormat df = new SimpleDateFormat(DateToolUtils.FORMAT_LONG_SSS);
        Calendar calendar = Calendar.getInstance();
        return df.format(calendar.getTime());
    }

    /**
     * 获取给定时间的毫秒数
     */
    public static Long getTimeCount(Date date) {
        return date.getTime();
    }

    /**
     * 获取当前时间的毫秒数
     */
    public static Long getNowTimeCount() {
        return System.currentTimeMillis();
    }

    /**
     * 获取日期年份
     * 
     * @param date
     *            日期
     * @return
     */
    public static String getYear(Date date) {
        String formatDate = format(date);
        return StringUtils.isNotBlank(formatDate) ? formatDate.substring(0, 4) : "";
    }

    /**
     * 按默认格式的字符串距离今天的天数
     * 
     * @param date
     *            日期字符串
     * @return
     */
    public static int countDays(String date) {
        long t = Calendar.getInstance().getTime().getTime();
        Calendar c = Calendar.getInstance();
        c.setTime(parse(date));
        long t1 = c.getTime().getTime();
        return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
    }

    /**
     * 按用户格式字符串距离今天的天数
     * 
     * @param date
     *            日期字符串
     * @param format
     *            日期格式
     * @return
     */
    public static int countDays(String date, String format) {
        long t = Calendar.getInstance().getTime().getTime();
        Calendar c = Calendar.getInstance();
        c.setTime(parse(date, format));
        long t1 = c.getTime().getTime();
        return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
    }

    /**
     * 计算从日期从(当前日期-n)(包括)日期开始 至 (当前日期-0)(包括)日期结束的<br>
     * </br>
     * 格式符合format(例如:yyyy-MM-dd)格式<br>
     * 且从小到大排列的 n个日期的列表<br>
     * <br>
     * 
     * @param format
     *            日期格式
     * @param n
     *            决定过去到今天的列表中的所有日期个数的参数
     * @return
     */
    public static List<String> dateLstDataByDateCount(String format, Integer n) {
        return dateLstDataByStartAndEnd(format, n, 0);
    }

    /**
     * 计算从日期从(当前日期-start)(包括)日期开始 至 (当前日期-end)(包括)日期结束的<br>
     * </br>
     * 格式符合format(例如:yyyy-MM-dd)格式<br>
     * 且从小到大排列的 <br>
     * 所有日期列表<br>
     * <br>
     * 
     * @param format
     *            日期格式
     * @param start
     *            决定日期起点的参数
     * @param end
     *            决定日期终点的参数
     */
    public static List<String> dateLstDataByStartAndEnd(String format, Integer start, Integer end) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        List<String> dateLst = new ArrayList<String>();
        if (end == null || start == null) {
            start = 0;
            end = 0;
        }
        if (end > start) {// 参数传值错误，处理办法，交换位置
            Integer middle = end;
            end = start;
            start = middle;
        }
        for (int i = start - 1; i >= end; i--) {
            Calendar c = Calendar.getInstance();
            c.add(Calendar.DATE, -i);
            String dateStr = sdf.format(c.getTime());
            dateLst.add(dateStr.toString());
        }
        return dateLst;
    }

    /**
     * 计算从日期从(当前月份-n)(包括)月份开始 至 (当前月份-0)(包括)月份结束的<br>
     * </br>
     * 格式符合format(例如:yyyy-MM-dd)格式<br>
     * 且从小到大排列的 n个日期的列表<br>
     * <br>
     * 
     * @param format
     *            日期月份格式
     * @param n
     *            决定过去到今天的列表中的所有月份日期个数的参数
     * @return
     */
    public static List<String> monthLstDataByDateCount(String format, Integer n) {
        return monthLstDataByStartAndEnd(format, n, 0);
    }

    /**
     * 计算从月份从(当前月份-start)(包括)月份开始 至 (当前月份-end)(包括)月份结束的<br>
     * </br>
     * 格式符合format(例如:yyyy-MM-dd)格式<br>
     * 且从小到大排列的 <br>
     * 所有月份列表<br>
     * <br>
     * 
     * @param format
     *            日期格式
     * @param start
     *            决定日期起点的参数
     * @param end
     *            决定日期终点的参数
     */
    public static List<String> monthLstDataByStartAndEnd(String format, Integer start, Integer end) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        List<String> dateLst = new ArrayList<String>();
        if (end == null || start == null) {
            start = 0;
            end = 0;
        }
        if (end > start) {// 参数传值错误，处理办法，交换位置
            Integer middle = end;
            end = start;
            start = middle;
        }
        for (int i = start - 1; i >= end; i--) {
            Calendar c = Calendar.getInstance();
            c.add(Calendar.MONTH, -i);
            String monthStr = sdf.format(c.getTime());
            dateLst.add(monthStr.toString());
        }
        return dateLst;
    }

    /**
     * 通过日期 和指定格式日期 返回前一天和后天的符合格式的日期<br>
     * </br>
     * 
     * @param date
     *            指定日期
     * @param format
     *            日期格式字符串
     * @return
     */
    public static List<String> findBeforeDayAndAfterDay(Date date, String format) {
        List<String> list = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String befterDay = sdf.format(DateUtils.addDays(date, -1));
        String toDay = sdf.format(date);
        String afterDay = sdf.format(DateUtils.addDays(date, 1));
        list.add(befterDay);
        list.add(toDay);
        list.add(afterDay);
        return list;
    }

    /**
     * 获取当前月的第一天
     * 
     */
    public static String getMothOfFirstDay(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
        String first = sdf.format(c.getTime());
        return first;
    }

    /**
     * 获取当前月的最后一天
     * 
     */
    public static String getMothOfLastDay(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        String last = sdf.format(ca.getTime());
        return last;
    }

    /**
     * 获取时间差处理返回字符串类型形式<br>
     * ## 1. afterDate - beforeDate > dateCount毫秒数时,<br>
     * beforeDate返回( yyyy-MM-dd HH:mm:ss) <br>
     * ## 2. afterDate - beforeDate <= dateCount毫秒数时,<br>
     * 返回afterDate - beforeDate(xx小时 xx 分钟 )
     */
    public String getDateIntervalProcessingFormat(Date beforeDate, Date afterDate, Long dateCount) {
        if (afterDate == null) {
            afterDate = new Date();
        }
        Long afterTimeCount = DateToolUtils.getTimeCount(afterDate);
        Long beforeTimeCount = DateToolUtils.getTimeCount(beforeDate);
        if (afterTimeCount - beforeTimeCount > dateCount) {// 发布时间超过一天
            return DateToolUtils.format(beforeDate, DateToolUtils.FORMAT_LONG);
        } else {
            Long timeCount = afterTimeCount - beforeTimeCount;
            int minuteOfInterval = (int) (timeCount / 1000 / 60);
            String timeStr = minuteOfInterval / 60 + "小时" + minuteOfInterval % 60 + "分钟之前 ";
            return timeStr;
        }
    }
}
